#!/usr/bin/env python
# This Python file uses the following encoding: utf-8

# Python kansrekening programma voor PWS (tekst versie)

# benodigde (functies / constanten uit) modules
from sys import exit    # Om netjes af te sluiten
from math import factorial as fact      # Hoeven we niet elke keer die lange naam in te tikken
from math import e      # Nodig voor de normale verdeling en poissionpdf
from math import pi # Nodig voor de normale verdeling
from math import sqrt # Nodig voor de normale verdeling
from Tkinter import * # GUI module
from sys import exit # Programma afsluiten

# functies voor rekenwerk / opslaan, etc.
def bereken_kans_simpel():
        """Berekent een simpele kans, door middel van een deling"""
        print "\nU moet enkele waardes invoeren zodat de berekening gemaakt kan worden."
        mogelijkheden_gunstig = float(raw_input("Hoeveel gunstige uitkomsten in het experiment?: "))
        mogelijkheden_totaal = float(raw_input("Hoeveel mogelijke uitkomosten in het experiment?: "))
        answer = mogelijkheden_gunstig / mogelijkheden_totaal
        print "\nDe kans is: ", answer
        opslaan = str(raw_input("\nWilt u deze waarde opslaan? Ja / Nee: "))
        if opslaan.lower() == "ja" or opslaan.lower() == "jaa" or opslaan.lower() == "yes":
                save_to_file(answer)
        

def binompdf(n = 0, X = 0, p = 0, OnRequest = 0):
        """Berekent een kans op een exacte waarde voor een binom. ver. kansvar. X"""
        if OnRequest == 0:
                print "\nU moet enkele waardes invoeren zodat de berekening gemaakt kan worden."
                n = int(raw_input("Wat is de waarde van n?: "))
                p = float(raw_input("Wat is de waarde van p?: "))
                desc_X = str(raw_input("Wat omschrijft de kansvariabele X?: "))
                X = float(raw_input("Op welke mogelijke waarde van X wilt u de kans berekenen?: "))
        answer = ((fact(n))/ (fact(X) * fact(n-X))) * (p ** X) * ((1 - p) ** (n - X))
        if OnRequest == 1:
                return answer
        print "\nDe kans op", int(X), desc_X, "is: ", answer
        opslaan = str(raw_input("\nWilt u deze waarde opslaan? Ja / Nee: "))
        if opslaan.lower() == "ja" or opslaan.lower() == "jaa" or opslaan.lower() == "yes":
                save_to_file(answer)
        
        # Hier is gebruikt gemaakt van P(X = k) = n boven k * p^k * (1 - p)^n-k
        # In python is dat de bovenstaande berekening, met behulp van de factorial functie
        # uit de math module. (Hernoemd tot fact, da's korter)

def binomcdf(n = 0, X = 0, p = 0, OnRequest = 0):
        """Berekent een kans op een waarde gelijk aan of kleiner dan n voor een binom. ver. kansvar. X"""
        if OnRequest == 0:
                print "\nU moet enkele waardes invoeren zodat de berekening gemaakt kan worden."
                n = int(raw_input("Wat is de waarde van n?: "))
                p = float(raw_input("Wat is de waarde van p?: "))
                desc_X = str(raw_input("Wat omschrijft de kansvariabele X?: "))
                X = float(raw_input("X moet kleiner zijn dan of gelijk zijn aan?: "))
        answer = 0
        for i in range(int(X + 1)):
                answer += binompdf(n, i, p, OnRequest = 1)
        if OnRequest == 1:
                return answer
        # De kans berekenen op alle waardes van X kleiner dan n en optellen
        print "\nDe kans op exact of minder dan", int(X), desc_X, "is: ", answer
        print "\nDe kans op meer dan", int(X), desc_X, "is dus: ", 1 - answer
        opslaan = str(raw_input("\nWilt u deze waarde opslaan? Ja / Nee: "))
        if opslaan.lower() == "ja" or opslaan.lower() == "jaa" or opslaan.lower() == "yes":
                save_to_file(answer)
        
def normalpdf(X = 0, gemiddelde = 0, standaardafwijking = 0, OnRequest = 0):
        """Berekent de kans op een waarde bij een normale verdeling, zoals normalpdf()"""
        if OnRequest == 0:
                print "\nU moet enkele waardes invoeren zodat de berekening gemaakt kan worden."
                gemiddelde = float(raw_input("gemiddelde?: "))
                standaardafwijking = float(raw_input("standaardafwijking?: "))
                desc_X = str(raw_input("Wat omschrijft de kansvariabele X?: "))
                X = float(raw_input("Van welke mogelijke waarde van X wilt u de kans berekenen?: "))
        answer = (1.0 / (sqrt(2 * pi * (standaardafwijking ** 2)))) * (e ** (-1 * ((X - gemiddelde) ** 2) / (2 * (standaardafwijking ** 2))))
        if OnRequest == 1:
                return answer
        print "\nDe kans op", int(X), desc_X, "is: ", answer
        print "\nOngeveer", (100 * answer), "% van de waarnemingen zal dus deze waarde opleveren."
        opslaan = str(raw_input("\nWilt u deze waarde opslaan? Ja / Nee: "))
        if opslaan.lower() == "ja" or opslaan.lower() == "jaa" or opslaan.lower() == "yes":
                save_to_file(answer)

def normalcdf(X = 0, gemiddelde = 0, standaardafwijking = 0, desc_X = 0, OnRequest = 0):
        """Berekent de kans dat bij normale verdeling waarde kleiner is dan X, zoals normalcdf()"""
        if OnRequest == 0:
                print "\nU moet enkele waardes invoeren zodat de berekening gemaakt kan worden."
                gemiddelde = float(raw_input("gemiddelde?: "))
                standaardafwijking = float(raw_input("standaardafwijking?: "))
                desc_X = str(raw_input("Wat omschrijft de kansvariabele X?: "))
                X = float(raw_input("Onder welke waarde moet X blijven?: "))
        limit = 6.0 * standaardafwijking  # Als we tot -10^99 moeten opdelen in driehoeken, chrasht de pc. Buiten 6 sigma bevindt zich toch praktisch niets.
        answer = 0
        deltaX = 0.00001   # nauwkeurig tot op 5 decimalen achter de komma, kleinere delta x is te traag.
        i = gemiddelde - limit
        while i < X:
                answer += (deltaX * normalpdf(i, gemiddelde, standaardafwijking, OnRequest = 1))
                i += deltaX
        if OnRequest == 1:
                return answer
        print "\nDe kans dat", desc_X, "kleiner is dan", int(X), "is: ", answer
        print "\nDe kans dat", desc_X, "groter is dan", int(X), "is dus: ", 1 - answer
        opslaan = str(raw_input("\nWilt u deze waarde opslaan? Ja / Nee: "))
        if opslaan.lower() == "ja" or opslaan.lower() == "jaa" or opslaan.lower() == "yes":
                save_to_file(answer)
                
def poissonpdf(frequentie = 0, tijd = 0, X = 0, OnRequest = 0):
	""" Berekent de kans dat in een bepaald tijdsbestek een bepaalde gebeurtenis een bepaald aantal keer voorkomt."""
	if OnRequest == 0:
		print "\nU moet enkele waardes invoeren zodat de berekening gemaakt kan worden."
		frequentie = float(raw_input("Om de hoeveel tijd komt de gebeurtenis gemiddeld voor? Geef een antwoord in minuten: "))
		per_minuut = 1 / frequentie
		tijd = int(raw_input("Hoe lang is de verstreken tijd? Geen een antwoord in minuten: "))
		X = int(raw_input("Hoe vaak moet de gebeurtenis in de verstreken tijd voorkomen?: "))
	aantal_verwacht = tijd * per_minuut
	answer = ((aantal_verwacht ** X) * (e ** (-1 * aantal_verwacht))) / (fact(X))
	if OnRequest == 1:
		return answer
	print "\nDe kans dat de gebeurtenis", X, "keer voorkomt in", tijd, "minuten is:", answer
	opslaan = str(raw_input("\nWilt u deze waarde opslaan? Ja / Nee: "))
	if opslaan.lower() == "ja" or opslaan.lower() == "nee" or opslaan.lower() == "yes":
		save_to_file(answer)
       
def test_hypothese(gemiddelde_verondersteld = 0, standaardafwijking = 0, n = 0, gemiddelde_waargenomen = 0, significantieniveau = 0, OnRequest = 0):
        """Rekent uit of een null-hypothese verworpen moet worden of niet"""
        if OnRequest == 0:
                print "\nU moet enkele waardes invoeren zodat de berekening gemaakt kan worden."
                gemiddelde_verondersteld = float(raw_input("gemiddelde volgens H0?: "))
                standaardafwijking = float(raw_input("standaardafwijking?: "))
                n = float(raw_input("aantal waarnemingen?: "))
                gemiddelde_waargenomen = float(raw_input("waargenomen gemiddelde?: "))
                significantieniveau = float(raw_input("significantieniveau?: "))
                overschrijdingskans = normalcdf(gemiddelde_waargenomen, gemiddelde_verondersteld, (standaardafwijking / sqrt(n)), OnRequest = 1)
        if overschrijdingskans > 0.5 * significantieniveau:
                answer = "De null-hypothese wordt niet verworpen."
        elif overschrijdingskans <= 0.5 * significantieniveau:
                answer = "De null-hypothese moet verworpen worden."
        if OnRequest == 1:
                return answer
        print "\n", answer
        opslaan = str(raw_input("\nWilt u deze uitkomst opslaan? Ja / Nee: "))
        if opslaan.lower() == "ja" or opslaan.lower() == "jaa" or opslaan.lower() == "yes":
                save_to_file(answer)
        
def save_to_file(value):
        """ Slaat de uitkomst van een berekening op"""
        file = open("uitkomsten.txt", "a")
        string = str(value) + "\n"
        file.write(string)
        file.close()

# GUI code

class Kansrekening:
    def __init__(self, master):
        frame = Frame(master)
        frame.grid()

        self.lblIntro = Label(frame, text = "Maak uw keuze:")
        self.lblIntro.grid(row = 0, sticky = W)

        self.bttn1 = Button(frame, text = "Een kans berekenen zonder kansvariabele", command = self.option1)
        self.bttn1.grid(row = 2, sticky = W,)

        self.bttn2 = Button(frame, text = "Een kans berekenen met een binomiaal verdeelde kansvariabele voor een exacte waarde (bv. X = 5) (als binompdf() op de GR)", command = self.option2)
        self.bttn2.grid(row = 3, sticky = W)

        self.bttn3 = Button(frame, text = "Een kans berekenen met een binomiaal verdeelde kansvariabele, gelijk aan of kleiner dan een bepaalde waarde (als binomcdf() op de GR)", command = self.option3)
        self.bttn3.grid(row = 4, sticky = W)

        self.bttn4 = Button(frame, text = "Een berekening met de normale verdeling maken voor een exacte waarde (bv. een pot bevat 1006 gram)", command = self.option4)
        self.bttn4.grid(row = 5, sticky = W)

        self.bttn5 = Button(frame, text = "Een berekening met de normale verdeling maken, de kans dat een waarde kleiner is dan X (bv. < 1006 gr)", command = self.option5)
        self.bttn5.grid(row = 6, sticky = W)

        self.bttn6 = Button(frame, text = "Een hypothese (H0) testen", command = self.option6)
        self.bttn6.grid(row = 8, sticky = W)
        
        self.bttn7 = Button(frame, text = "De kans berekenen dat een bepaalde gebeurtenis in een bepaald tijdsbestek een bepaald aantal keer voorkomt. (Poissonpdf)", command = self.option7)
        self.bttn7.grid(row = 7, sticky = W)

        self.bttnExit = Button(frame, text = "afsluiten", command = self.option8)
        self.bttnExit.grid(row = 8, sticky = E)

    def option1(self):
        bereken_kans_simpel()

    def option2(self):
        binompdf()

    def option3(self):
        binomcdf()

    def option4(self):
        normalpdf()

    def option5(self):
        normalcdf()

    def option6(self):
        test_hypothese()
    
    def option7(self):
		poissonpdf()

    def option8(self):
        exit()

root = Tk()
root.geometry("1000x500")
app = Kansrekening(root)
root.mainloop()
